package javaapplication6;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Properties;

// Класс загрузки по протоколу Http
public class HttpDownloader extends Dowloader{
	public HttpDownloader(URL url, String outputFolder, int numConnections,ProxySettings PS) {
		super(url, outputFolder, numConnections,PS);
		download();
	}
// Функция обработки ошибок
	private void error() {
		System.out.println("ERROR");

		setState(ERROR);
	}

	@Override
	public void run() {
		HttpURLConnection conn = null;
                if(mproxyRequired==true)
                {Properties systemSettings = System.getProperties();
                 systemSettings.put("http.proxyHost",mproxyIP);
                 systemSettings.put("http.proxyHost",mproxyPort);
                 System.setProperties(systemSettings);
                }
		try {
			
			conn = (HttpURLConnection)mURL.openConnection();
                        if(mproxyRequired==true)
                        {
                String encoded = new String(new sun.misc.BASE64Encoder().encode(new String( mproxyUsername + ":" + mproxyPassword).getBytes()));
                conn.setRequestProperty("Proxy-Authorization", "Basic " + encoded);

                        }
			conn.connect();
            // Проверка кода ответа
            if (conn.getResponseCode() / 100 != 2) {
                error();
            }
            // Проверка размера файла
            int contentLength = conn.getContentLength();
            if (contentLength < 1) {
                error();
            }
            if (mFileSize == -1) {
            	mFileSize = contentLength;
            	stateChanged();
            	System.out.println("File size: " + mFileSize);
            }
            if (conn != null)
				conn.disconnect();
// Если нет ошибок и статус DOWNLOADING
            if (mState == DOWNLOADING) {
                // Если список потоков загрузки пуст
            	if (mListDownloadThread.size() == 0)
            	{// Если размер больше минимального для 1 потока
            		if (mFileSize > MIN_DOWNLOAD_SIZE) {
						int partSize = Math.round(((float)mFileSize / mNumConnections) / BLOCK_SIZE) * BLOCK_SIZE;
						System.out.println("Part size: " + partSize);
						int startByte = 0;
						int endByte = partSize - 1;
						HttpDownloadThread aThread = new HttpDownloadThread(1, mURL, mOutputFolder + mFileName, startByte, endByte);
						mListDownloadThread.add(aThread);
						int i = 2;
						while (endByte < mFileSize) {
							startByte = endByte + 1;
							endByte += partSize;
							aThread = new HttpDownloadThread(i, mURL, mOutputFolder + mFileName, startByte, endByte);
							mListDownloadThread.add(aThread);
							i++;
						}
            		} else
            		{
            			HttpDownloadThread aThread = new HttpDownloadThread(1, mURL, mOutputFolder + mFileName, 0, mFileSize);
						mListDownloadThread.add(aThread);
            		}
            	} else { 
            		for (int i=0; i<mListDownloadThread.size(); ++i) {
            			if (!mListDownloadThread.get(i).isFinished())
            				mListDownloadThread.get(i).download();
            		}
            	}

				// Ожидание завершения всех потоков
				for (int i=0; i<mListDownloadThread.size(); ++i) {
					mListDownloadThread.get(i).waitFinish();
				}
				if (mState == DOWNLOADING) {
					setState(COMPLETED);
				}
            }
		} catch (Exception e) {
			error();
		} finally {
			if (conn != null)
				conn.disconnect();
		}
	}

       // Класс потока загрузки
	private class HttpDownloadThread extends DownloadThread {

	// Конструктор класса HttpDownloadThread
		public HttpDownloadThread(int threadID, URL url, String outputFile, int startByte, int endByte) {
			super(threadID, url, outputFile, startByte, endByte);
		}

		@Override
		 public  void   run() {
			BufferedInputStream in = null;
			RandomAccessFile raf = null;
                        HttpURLConnection conn = null;
                    
			try {if(mproxyRequired==true)
                   {Properties systemSettings = System.getProperties();
                 systemSettings.put("http.proxyHost",mproxyIP);
                 systemSettings.put("http.proxyHost",mproxyPort);
                 System.setProperties(systemSettings);
                  }
				 conn = (HttpURLConnection)mURL.openConnection();
				String byteRange = mStartByte + "-" + mEndByte;
				conn.setRequestProperty("Range", "bytes=" + byteRange);
				System.out.println("bytes=" + byteRange);
                                if(mproxyRequired==true)
                        {
                String encoded = new String(new sun.misc.BASE64Encoder().encode(new String( mproxyUsername + ":" + mproxyPassword).getBytes()));
                conn.setRequestProperty("Proxy-Authorization", "Basic " + encoded);

                        }
				conn.connect();

				// Проверка кода ответа
	            if (conn.getResponseCode() / 100 != 2) {
	                error();
	            }  
				in = new BufferedInputStream(conn.getInputStream());
				raf = new RandomAccessFile(mOutputFile, "rw");
				raf.seek(mStartByte);
				byte data[] = new byte[BUFFER_SIZE];
				int numRead;
				while((mState == DOWNLOADING) && ((numRead = in.read(data,0,BUFFER_SIZE)) != -1))
				{
					raf.write(data,0,numRead);
					mStartByte += numRead;
					downloaded(numRead);
				}
                                

                            

                            
				if (mState == DOWNLOADING) {
					mIsFinished = true;
				}
                                
			} catch (IOException e) {
				error();
                                 System.out.println("Error=" + e);
            e.printStackTrace();
			} finally {

				if (raf != null) {
					try {
						raf.close();
					} catch (IOException e) {}
				}

				if (in != null) {
					try {
						in.close();
					} catch (IOException e) {}

				} 
			}

			System.out.println("End thread " + mThreadID);
		}
            }
    
}
